package com.ly.mpayment.core.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.ly.mpayment.persist.common.CustomUUID;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

/**
 * TreeUtil.java
 * 树状数据工具类
 * 2013-6-29
 * Version 1.0
 */
public class TreeUtil {
	
	/**
	 * 格式化list为json字符串
	 * @param list list数据
	 * @param excludes 过滤的字段数组
	 * @return
	 */
	@SuppressWarnings({"rawtypes" })
	public static String formatListToJson(List<?> list,String [] excludes,String sortField,String sortType){
		if(list.isEmpty()){
			return null;
		}else{
			//获取类模版
			Class classModel = list.get(0).getClass();
			JsonConfig config = new JsonConfig();
			config.setExcludes(excludes);
			config.registerJsonValueProcessor(Date.class, new JsonValueFormat()); 
			config.registerJsonValueProcessor(CustomUUID.class, new CustomJsonValueProcessor());
			JSONArray array = JSONArray.fromObject(list, config);
//			//将子节点转换为List
//			list = JSONArray.toCollection(array, config).toArray();
//			//排序
//			new ListSortUtil().Sort(list, sortField, sortType);							
//			//将排序后的节点按照json配置再次转为json数组
//			array = JSONArray.fromObject(list, config);
			return formatArrayToStr(array, config, classModel,sortField,sortType).toString();
		}	
	}
	
	/**
	 * 格式化list为json字符串
	 * @param list list数据
	 * @param excludes 过滤的字段数组
	 * @return
	 */
	@SuppressWarnings({"rawtypes"})
	public static String formatListToJson2(List<?> list,String [] excludes,String sortField,String sortType){
		if(list.isEmpty()){
			return null;
		}else{
			//获取类模版
			Class classModel = list.get(0).getClass();
			JsonConfig config = new JsonConfig();
			config.setExcludes(excludes);
			config.registerJsonValueProcessor(Date.class, new JsonValueFormat()); 
			JSONArray array = JSONArray.fromObject(list, config);
//			//将子节点转换为List
//			list = JSONArray.toList(array, classModel);
//			//排序
//			new ListSortUtil().Sort(list, sortField, sortType);							
//			//将排序后的节点按照json配置再次转为json数组
//			array = JSONArray.fromObject(list, config);
			return formatArrayToStr2(array, config, classModel,sortField,sortType).toString();
		}	
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static JSONArray formatArrayToStr2(JSONArray array,JsonConfig config,Class classModel,String sortField,String sortType){
		String childrenPropertyName = "children";	
		//遍历数组
		for (int i = 0; i < array.size(); i++) {
			//获取菜单每个节点
			JSONObject obj = array.getJSONObject(i);
			//取出节点中的子节点属性
			if(obj.containsKey(childrenPropertyName)){
				JSONArray temp = obj.getJSONArray(childrenPropertyName);
				//如果子节点为空
				if(temp.isEmpty()){
					continue;
				}else{		
					//将子节点转换为List
					List list = null;
					try {
						list = toList(temp,classModel);
					} catch (Exception e) {
						e.printStackTrace();
					}
					//排序
					new ListSortUtil().Sort(list, sortField, sortType);					
				
					//将排序后的节点按照json配置再次转为json数组
					temp = JSONArray.fromObject(list, config);
					//回调方法，如果子节点下还有节点
					temp = formatArrayToStr(temp,config,classModel,sortField,sortType);
					obj = obj.element(childrenPropertyName, temp);
					array.set(i, obj); 
				}
			}else{
				obj.element(childrenPropertyName, new JSONArray());
			}
		}
		return array;
	}
	
	/**
	 * 将数组转换为字符串
	 * @param array 
	 * @param config
	 * @param classModel
	 * @param childrenPropertyName
	 * @return
	 * @throws IllegalAccessException 
	 * @throws Exception 
	 */
	@SuppressWarnings({ "rawtypes", "unchecked"})
	private static JSONArray formatArrayToStr(JSONArray array,JsonConfig config,Class classModel,String sortField,String sortType){
		String childrenPropertyName = "children";	
		//遍历数组
		for (int i = 0; i < array.size(); i++) {
			//获取菜单每个节点
			JSONObject obj = array.getJSONObject(i);
			//取出节点中的子节点属性
			if(obj.containsKey(childrenPropertyName)){
				JSONArray temp = obj.getJSONArray(childrenPropertyName);
				//如果子节点为空
				if(temp.isEmpty()){
					//删除子节点属性
					obj.remove(childrenPropertyName);
				}else{		
					//将子节点转换为List
					List list = null;
					try {
						list = toList(temp,classModel);
					} catch (Exception e) {
//						LogUtil.saveError(e);
						e.printStackTrace();
					}
					//排序
					new ListSortUtil().Sort(list, sortField, sortType);					
				
					//将排序后的节点按照json配置再次转为json数组
					temp = JSONArray.fromObject(list, config);
					//回调方法，如果子节点下还有节点
					temp = formatArrayToStr(temp,config,classModel,sortField,sortType);
					obj = obj.element(childrenPropertyName, temp);
					array.set(i, obj); 
				}
			}	
		}
		return array;
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static List toList(JSONArray temp, Class classModel) throws Exception{
		List list = new ArrayList();
		for (int i = 0; i < temp.size(); i++) {
			Object bean = classModel.newInstance();
			JSONObject json = temp.getJSONObject(i);
			Set set = json.keySet();
			for (Object key : set) {
				Field field = classModel.getDeclaredField(key.toString());
				Class c = field.getType();
				String methodName = "set" + firstToUpper(key.toString());
				Method m = classModel.getDeclaredMethod(methodName,c);
				if(Set.class.isAssignableFrom(c)){
					JSONArray child = json.getJSONArray(key.toString());
					List childList = toList(child, classModel);
					Set s = new HashSet();
					for (Object object : childList) {
						s.add(object);
					}
					m.invoke(bean, s);
				}else if(Date.class.isAssignableFrom(c)){
					Date date = DateUtils.convert(json.getString(key.toString()));
					m.invoke(bean, date);
				}else if(CustomUUID.class.isAssignableFrom(c)){
					CustomUUID customUUID = new CustomUUID(json.get(key).toString());
					m.invoke(bean, customUUID);
				}else{
					m.invoke(bean, json.get(key));
				}
				
			}
			list.add(bean);
		}
		return list;
	}
	
	private static String firstToUpper(String str){
		String first = str.substring(0,1).toUpperCase();
		String other = str.substring(1, str.length());
		return first+other;
	}

	/** 子节点为空则移除该属性
	 * @param list
	 * @return
	 */  
	public static String excludNullChildren(List<?> list){
		JSONArray array = JSONArray.fromObject(list);
		array = removeChildren(array);
		return array.toString();
	}

	private static JSONArray removeChildren(JSONArray array){
		String childrenPropertyName = "children";	
		for (int i = 0; i < array.size(); i++) {
			JSONObject obj = array.getJSONObject(i);
			JSONArray temp = obj.getJSONArray(childrenPropertyName);
			if(temp.isEmpty()){
				//删除子节点属性
				obj.remove(childrenPropertyName);
			}else{
				temp = removeChildren(temp);
			}
		}
		return array;
	}
}
